package com.dingding.special.order.calculation.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.http.HttpStatus;
import org.apache.log4j.Logger;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.dingding.common.core.base.daox.ICriteriaBaseDao;
import com.dingding.common.core.base.dto.AbstractValiResponse;
import com.dingding.common.core.base.dto.ResponseEntity;
import com.dingding.common.core.beans.UserLogin;
import com.dingding.common.core.beans.special.SpecialDrivingRecord;
import com.dingding.common.core.beans.special.UserspecialorderT;
import com.dingding.common.core.util.DateFormatUtil;
import com.dingding.common.core.util.GetDistanceUtil;
import com.dingding.common.core.util.JSONUtil;
import com.dingding.common.core.util.bean.BeanUtilx;
import com.dingding.common.core.util.paravalidate.ValiResult;
import com.dingding.common.core.util.paravalidate.ValidateUtil;
import com.dingding.facade.queue.dto.push.PushRequestDTO;
import com.dingding.facade.queue.enums.ClientType;
import com.dingding.facade.queue.enums.PushType;
import com.dingding.facade.queue.facade.IQueueFacade;
import com.dingding.facade.special.trasfer.calc_price.ReqCalculationAmountDTO;
import com.dingding.facade.special.trasfer.calc_price.ResCalculationAmountDTO;
import com.dingding.order.dto.publish.PushData;
import com.dingding.special.order.calculation.message.CalculationAmountMessage;
import com.dingding.special.order.calculation.service.ICalCulatePriceService;
import com.dingding.special.order.calculation.service.ICalculationAmountService;
import com.dingding.special.user.userinfo.dao.ISpecialUserInfoDao;

/**
 * 
 * @ClassName: CalculationAmountServiceImpl 
 * @Description: 实时计算价格
 * @author CHEHAUNBO 
 * @date 2016年8月31日 上午10:37:22
 * @since V2.4.0
 * 
 */
@Component("calculationAmountService")
public class CalculationAmountServiceImpl extends AbstractValiResponse implements ICalculationAmountService {

	@Resource(name = "criteriaBaseDao")
	private ICriteriaBaseDao criteriaBaseDao;

	@Resource(name = "specialUserInfoDao")
	private ISpecialUserInfoDao specialUserInfoDao;

	@Resource(name = "queueService")
	private IQueueFacade queueFacade;

	@Resource(name = "calcuatePriceService")
	private ICalCulatePriceService calCulatePriceService;

	private static final Logger log = Logger.getLogger(CalculationAmountServiceImpl.class);

	/**
	 * 
	 * 实时计算价格
	 * 
	 * @Title: calculationAmount 
	 * @author CHEHAUNBO
	 * @since V2.4.0
	 * 
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
	public ResponseEntity<ResCalculationAmountDTO> calculationAmount(ReqCalculationAmountDTO reqCalculationAmountDTO) {

		ValiResult valiResult = ValidateUtil.validateBeanIsAvaliable(reqCalculationAmountDTO,
				ReqCalculationAmountDTO.class);
		// 参数不合法，存在空值
		if (!valiResult.isAvailable()) {
			return super.error(valiResult);
		}

		// 获取订单信息
		Criterion order_criterion = Restrictions.eq("specialOrderId", reqCalculationAmountDTO.getOid());
		UserspecialorderT userspecialorderT = criteriaBaseDao.queryCriteriaListUnique(UserspecialorderT.class,
				order_criterion);

		if (userspecialorderT != null) {

			double lastlongitude = userspecialorderT.getAboardLongitude(); // 上次的经度
			double lastlatitude = userspecialorderT.getAboardLatitude(); // 上次的纬度

			BigDecimal totalDistance = new BigDecimal(0);// 总行驶距离
			BigDecimal stageDistance = new BigDecimal(0);// 临时变量
			BigDecimal duration = new BigDecimal(0); // 在线时长
			BigDecimal amount = new BigDecimal(0); // 金额
			Criterion criterion = Restrictions.eq("orderId", reqCalculationAmountDTO.getOid());
			List<SpecialDrivingRecord> drivingRecords = criteriaBaseDao.queryCriteriaList(SpecialDrivingRecord.class,
					criterion);

			if (drivingRecords != null && drivingRecords.size() > 0) {

				// 计算出行驶总里程
				for (SpecialDrivingRecord drivingRecord : drivingRecords) {

					stageDistance = GetDistanceUtil.GetDistance(lastlongitude, lastlatitude,
							drivingRecord.getLongitude(), drivingRecord.getLatitude());
					totalDistance = totalDistance.add(stageDistance);
					lastlongitude = drivingRecord.getLongitude();
					lastlatitude = drivingRecord.getLatitude();

				}

			}

			stageDistance = GetDistanceUtil.GetDistance(lastlongitude, lastlatitude,
					reqCalculationAmountDTO.getLongitude(), reqCalculationAmountDTO.getLatitude());
			totalDistance = totalDistance.add(stageDistance);
			duration = DateFormatUtil.dateMin(userspecialorderT.getAboardTime(), new Date());
			// 金额
			amount = calCulatePriceService.calculatePrice(totalDistance, userspecialorderT.getPlaceOrderCityCode());
			amount = amount.add(duration.multiply(new BigDecimal(0.5)));

			ResCalculationAmountDTO calculationAmountDTO = new ResCalculationAmountDTO();
			
			userspecialorderT.setDuration(duration);

			// 保存数据
			SpecialDrivingRecord specialDrivingRecord = new SpecialDrivingRecord();
			BeanUtilx.copyProperties(specialDrivingRecord, reqCalculationAmountDTO);
			specialDrivingRecord.setSdrId(UUID.randomUUID().toString());
			specialDrivingRecord.setCreateTime(new Date());
//			specialDrivingRecord.setDuration(duration); // 时长
			specialDrivingRecord.setOrderId(reqCalculationAmountDTO.getOid());

			if(userspecialorderT.getPublishType() == 3){
				
				// 时长
				calculationAmountDTO.setDuration(duration);
				// 距离
				calculationAmountDTO.setDistance(totalDistance);
				// 金额
				calculationAmountDTO.setAmount(amount);
				calculationAmountDTO.setOid(reqCalculationAmountDTO.getOid());
				calculationAmountDTO.setPublishType(userspecialorderT.getPublishType()); // 专车
				
				userspecialorderT.setTotalMoney(calculationAmountDTO.getAmount());
				userspecialorderT.setDistance(calculationAmountDTO.getDistance());
				
//				specialDrivingRecord.setAmount(amount); // 金额
//				specialDrivingRecord.setTravelDistance(totalDistance);// 距离

			}else{
				
				// 时长
				calculationAmountDTO.setDuration(duration);
				// 距离
				calculationAmountDTO.setDistance(userspecialorderT.getDistance());
				// 金额
				calculationAmountDTO.setAmount(userspecialorderT.getTotalMoney());
				
//				specialDrivingRecord.setAmount(userspecialorderT.getTotalMoney()); // 金额
//				specialDrivingRecord.setTravelDistance(userspecialorderT.getDistance());// 距离
			}
			
			
			try {
				criteriaBaseDao.save(specialDrivingRecord);
				// 添加消息到队列中
				createPush(userspecialorderT.getPlaceOrderUserId(), calculationAmountDTO);
				return super.success(calculationAmountDTO, HttpStatus.SC_OK);
			} catch (Exception e) {
				log.error("实时计算价格，保存用户位置信息出现异常！", e);
				return super.error(HttpStatus.SC_INTERNAL_SERVER_ERROR,
						CalculationAmountMessage.CALCULATION_AMOUNT_ERROR, CalculationAmountMessage.SERVER_ERROR);
			}

		} else {
			return super.error(HttpStatus.SC_INTERNAL_SERVER_ERROR, CalculationAmountMessage.ORDER_NOT_EXISTS,
					CalculationAmountMessage.APP_ERROR);
		}

	}

	@Override
	public void createPush(String userId, ResCalculationAmountDTO resCalculationAmountDTO) {

		// 获取推送内容
		UserLogin userLogin = criteriaBaseDao.getById(userId, UserLogin.class);

		// 推送Bean
		PushData pushData = new PushData();

		// 推送序号(时间戳)
		pushData.setRequestNumber(DateFormatUtil.getTimeInMillis().toString());
		// 推送时间
		pushData.setRequestTime(DateFormatUtil.yyyy_MM_dd_HHmmss());
		// 模块
		pushData.setModular("calcuationAmountPush");
		pushData.setResponseBody(resCalculationAmountDTO);

		PushRequestDTO pushRequestDTO = new PushRequestDTO();
		// 推送别名
		pushRequestDTO.setAliasId(userLogin.getAliasId());
		// 设备类型
		if (userLogin.getLoginEquipment() == 2) {
			pushRequestDTO.setClientType(ClientType.Android);
		} else if (userLogin.getLoginEquipment() == 1) {
			pushRequestDTO.setClientType(ClientType.iOS);
		}

		// 消息推送类型
		pushRequestDTO.setPushType(PushType.msgcontent);

		// 推送类型
		pushRequestDTO.setPushContent(JSONUtil.toJSONString(pushData));

		queueFacade.addPushToQueue(JSONUtil.toJSONString(pushRequestDTO));

	}

}
